/// 
/// MaDAson - Toolkit for Model Driven Software Development
/// 
/// Copyright [2006] Marcus Lankenau
/// 
/// Licensed under the Apache License, Version 2.0 (the "License");
/// you may not use this file except in compliance with the License.
/// You may obtain a copy of the License at
///  
///     http://www.apache.org/licenses/LICENSE-2.0
///  
/// Unless required by applicable law or agreed to in writing, software
/// distributed under the License is distributed on an "AS IS" BASIS,
/// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
/// See the License for the specific language governing permissions and
/// limitations under the License.
/// 

using System;
using System.Collections.Generic;
using System.Text;
using System.Xml;

namespace Madason.MetaModel.Interfaces
{
	public class ExportXmi11 : IMetaModelExport
	{
		//const string umlns = "href://omg.org/UML1.3";
		const string umlns = "href://org.omg/UML/1.3";
		XmlWriter writer = null;

		public void WriteModelElement(ModelElement me)
		{
			writer.WriteAttributeString("name", me.Name);
			if (me.Id == null || me.Id == "") me.Id = Guid.NewGuid().ToString();
			writer.WriteAttributeString("xmi.id", me.Id);
		}

		public void WriteAttribute(Attribute attr)
		{
			writer.WriteStartElement("Attribute", umlns);
			writer.WriteAttributeString("type", attr.TypeId);
			WriteModelElement(attr);
			writer.WriteEndElement(); // Attribute
		}

		public void WriteClass(Class cls)
		{
			if (cls is Datatype)
			{
				writer.WriteStartElement("DataType", umlns);
				WriteModelElement(cls);
				writer.WriteEndElement(); // Datatype
			}
			else
			{
				writer.WriteStartElement("Class", umlns);
				WriteModelElement(cls);
				writer.WriteStartElement("Classifier.feature", umlns);

				foreach (Attribute attr in cls.Attributes)
				{
					WriteAttribute(attr);
				}

				writer.WriteEndElement(); // Classifier.feature
				writer.WriteEndElement(); // Class
			}
		}


		public void WriteNamespace(Namespace ns)
		{
			if (ns is Model)
				writer.WriteStartElement("Model", umlns);
			else
				writer.WriteStartElement("Package", umlns);					
			WriteModelElement(ns);

			writer.WriteStartElement("Namespace.ownedElement", umlns);
			foreach (Class cls in ns.Classes)
			{
				WriteClass(cls);
			}
			foreach (Namespace childNs in ns.Namespaces)
			{
				WriteNamespace(childNs);
			}
			writer.WriteEndElement(); // Namespace.ownedElement

			writer.WriteEndElement(); // Model/Namspace
		}

		/// <summary>
		/// Write the XMI Body
		/// </summary>
		/// <param name="model"></param>
		public void WriteXmi(Model model)
		{
			
			writer.WriteStartDocument();

			writer.WriteStartElement("XMI");			
			writer.WriteAttributeString("xmi.version", "1.1");
			writer.WriteAttributeString("xmlns", "UML", null, umlns);
			
			writer.WriteAttributeString("timestamp", DateTime.Now.ToString()); // todo, set to us-local
			
			writer.WriteStartElement("XMI.header");
			writer.WriteStartElement("XMI.documentation");
			writer.WriteStartElement("XMI.exporter");
			writer.WriteValue("MaDAson");
			writer.WriteEndElement(); // XMI.exporter
			writer.WriteStartElement("XMI.exporterVersion");
			writer.WriteValue("1.0");
			writer.WriteEndElement(); // XMI.exporterVersion
			writer.WriteEndElement(); // XMI.documentation
			writer.WriteEndElement(); // XMI.header
			writer.WriteStartElement("XMI.content");
			WriteNamespace(model);
			writer.WriteEndElement(); // XMI.content
			writer.WriteEndElement(); // XMI
		}


		public void Export(Model model, System.IO.TextWriter writer)
		{
			XmlWriterSettings settings = new XmlWriterSettings();
			settings.Encoding = Encoding.UTF8;
			settings.Indent = true;
			using (this.writer = XmlWriter.Create(writer, settings))
			{
				WriteXmi(model);	

			}			
		}

	}
}
